﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Office.Interop.PowerPoint;
using Microsoft.Office.Interop;
using System.Net;
using Common;
using Common.Protocol;
using System.Web.Script.Serialization;
using System.ServiceModel;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace PPTControl
{
    class WorkerThread
    {
        private Thread _holderThread;
        private Microsoft.Office.Interop.PowerPoint.Application _app;
        private int _uid;
        private int seqNo = 0;
        private IProxy _proxy = null;
        private Form1 _mainForm = null;
        public LoginReq LoginInfo
        {
            get;
            set;
        }
        public Microsoft.Office.Interop.PowerPoint.Application App
        {
            get { return _app; }
            set { _app = value; }
        }
        private bool _zoomed = false;
        public WorkerThread(Microsoft.Office.Interop.PowerPoint.Application app, Form1 mainForm, int uid, IProxy proxy)
        {
            _app = app;
            _mainForm = mainForm;
            _uid = uid;
            _holderThread = new Thread(new ThreadStart(doWork));
            _proxy = proxy;
            _holderThread.Start();
            _zoomed = false;
       
        }

        protected void doWork()
        {
            while (true)
            {
                try
                {
                    Logger.Write("loop begin");
                    CheckResp ctrlCmd = CheckRequest();
                    if (ctrlCmd == null)
                        continue;

                    Logger.Write(ctrlCmd.ToJson());
                    ControlResp response = HandleCtrlRequest(ctrlCmd);
                    if (response != null)
                    {
                        Logger.Write(response.ToString());
                        Response(response);
                    }
                    else
                    {
                        Logger.Write("no response needed.");
                    }
                }
                catch (Exception ex)
                {
                    Logger.Write(ex.ToString());
                    if (ex.GetType() == typeof(ThreadAbortException))
                    {
                        break;
                    }
                    }
                 
            }
            
            CleanContext();
            return;
          
        }
        public void Stop()
        {
            CleanContext();
            _holderThread.Abort();
        }

        private void CleanContext()
        {
            _app = null;
            if (_proxy != null)
                _proxy.Deinit();
            _proxy = null;
        }
        private CheckResp CheckRequest()
        {
            CheckReq reqCmd = new CheckReq();
            reqCmd.Uid = _uid;
            reqCmd.SeqNO = seqNo;
            try
            {
                CheckResp respCmd = _proxy.CheckCommand(reqCmd);
                return respCmd;
            }
            catch (Exception e)
            {
                return null;
            }
        }
        const int CHECKREQ_TIMEOUT = 20 * 60 * 1000;//20 MINUTES
        const int RESPONSE_TIMEOUT = 10 * 1000; // 10 SECONDS
        void Response(ControlResp response )
        {
            response.Uid = _uid;
            _proxy.ResponseCommand(response);
        }

        private void Zoom(bool zoomIn)
        {
            if(zoomIn&&!_zoomed)
            {
                ScreenUtil.ZoomIn(_mainForm);
                _zoomed = true;
            }
            else if(!zoomIn&&_zoomed)
            {
                ScreenUtil.ZoomOut(_mainForm);
                _zoomed = false;
            }
        }

        private ControlResp ChangePage(ControlReq.OperationType op)
        {
            if(_zoomed)
            {
                Zoom(false);
            }

            if (op == ControlReq.OperationType.Right)
            {
                return PPTUtil.Next(_app);
            }
            else
            {
                return PPTUtil.Previous(_app);
            }
        }

        void LocateTo(double x, double y)
        {

            Point phyPt = MouseUtil.LogicToScreen(x,y);
            string log = string.Format("x:{0} y:{1} posx:{2} posY:{3}", phyPt.X, phyPt.Y, x,y);
            Logger.Write(log);
            
            MouseUtil.Locate(phyPt.X,phyPt.Y);
           
            if (_zoomed)
            {
                _mainForm.MoveManiger(phyPt);
            }
            
        }
        private ControlResp HandleCtrlRequest(CheckResp request)
        {
            ControlResp response = new ControlResp();
            response.Comments = "comments";
            response.PageNO = 0;
       
            try
            {
                ControlReq.OperationType op = request.GetOperationType();
                switch(op)
                {
                    case ControlReq.OperationType.Right:
                        response = ChangePage(op);
                        break;
                    case ControlReq.OperationType.Left:
                        response = ChangePage(op);
                        break;

                    case ControlReq.OperationType.MouseMove:
                        //response = MouseUtil.Move(request.OffsetX, request.OffsetY);
                        break;
                    case ControlReq.OperationType.ZoomIn:
                        Zoom(true);
                        break;
                    case ControlReq.OperationType.ZoomOut:
                        Zoom(false);
                        break;
                    case ControlReq.OperationType.Location:
                        LocateTo(request.OffsetX, request.OffsetY);
                        break;
                }

            }
            catch(Exception ex)
            {
                Logger.Write(ex.ToString());
                response.PageNO =0;
            }
            if (request.Process == ControlReq.ProcessType.WaitForResponse.ToString())
                return response;
            else
                return null;
        }
    }
}
